/**
 * Copyright (c) 2010-2011 julewa.com.  
 * All rights reserved. 
 * 
 * @author Huang Benhua
 * @date 2011-2-20
 * 
**/
package com.julewa.loading;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;

import org.apache.commons.lang.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.ContextLoader;

import com.julewa.db.BeanValidator;
import com.julewa.db.NoDatabase;
import com.julewa.db.mongo.MongoDB;
import com.julewa.freemarker.FreemarkerBuilder;
import com.julewa.freemarker.FreemarkerManager;
import com.julewa.freemarker.method.FM_Q;
import com.julewa.freemarker.method.FM_QURL;
import com.julewa.freemarker.method.FM_S;
import com.julewa.freemarker.method.FM_URL;
import com.julewa.freemarker.method.FM_UTILS;

@SuppressWarnings("rawtypes")
public final class SpringLoader {
	private ServletContext servletContext = null;
	private ContextLoader springContext = null;
	public SpringLoader(){}
	public SpringLoader(FreemarkerBuilder spring, FreemarkerBuilder properties){
		Map<String, String> beans = new HashMap<String, String>();
		this.load_freemarker_properties(properties, beans);
		load_global_beans(beans);
		push_class(beans, PreInterceptor.class);
		push_class(beans, ClientImpl.class);
		push_class(beans, BeanValidator.class);
		push_class(beans, TextsImpl.class);
		push_class(beans, FM_UTILS.class);
		//
		push_class(beans, MongoDB.class);
		//
		beans.put("Q", FM_Q.class.getCanonicalName());
		beans.put("S", FM_S.class.getCanonicalName());
		beans.put("URL", FM_URL.class.getCanonicalName());
		beans.put("QURL", FM_QURL.class.getCanonicalName()); 
		//
		spring.put("beans", beans.entrySet());
		spring.put("package_base", SystemUtils.getProperty("system.package") + ".**");
		spring.build(SystemUtils.getClassesPath() + "_JULEWA_SPRING_.xml");
		//
	}
	public static void push_class(Map<String, String> beans, Class<?> c){
		beans.put(c.getCanonicalName(), c.getCanonicalName());
	}
	public static ApplicationContext load_test_context(Map<String, String> beans){
		SpringLoader.load_global_beans(beans);
		//create config
		FreemarkerBuilder freemarker = new FreemarkerManager(StrutsLoader.class).load("spring");
		freemarker.put("beans", beans.entrySet());
		freemarker.put("package_base", SystemUtils.getProperty("system.package") + ".**");
		freemarker.build(SystemUtils.getClassesPath() + "_JULEWA_SPRING_TEST_.xml");
		//
		return new ClassPathXmlApplicationContext("_JULEWA_SPRING_TEST_.xml");
	}
	private static void load_global_beans(Map<String, String> beans){
		push_class(beans, ConfigurationImpl.class);
		push_class(beans, ContentType.class);
		push_class(beans, SpringLoggerProcessor.class);
		//
		Set<String> keys = SystemUtils.getKeys();
		for(String k:keys){
			if(!k.startsWith("spring."))continue;
			k = SystemUtils.getProperty(k);
			beans.put(k, k);
		}
		//
		String dbBeans[] = SystemUtils.getProperty("system.db", "").split(",");
		boolean hasDbImpl = false;
		for(String b: dbBeans){
			if(StringUtils.isBlank(b))continue;
			beans.put(b, b);
			hasDbImpl = true;
		}
		if(!hasDbImpl){
			push_class(beans, NoDatabase.class);
		}
	}
	
	private void load_freemarker_properties(FreemarkerBuilder properties, Map<String, String> beans){
		//SystemUtils.setProperty("freemarker.method.query", FreemarkerQuerier.class.getCanonicalName());
		properties.getParameters().clear();
		Map<String, String> props = new HashMap<String, String>();
		Set<String> keys = SystemUtils.getKeys();
		for(String k:keys){
			if(!k.startsWith("freemarker."))continue;
			if(k.startsWith("freemarker.method.")){
				String v = SystemUtils.getProperty(k);
				beans.put(v, v);
				continue;
			}
			props.put(k.substring("freemarker.".length()), SystemUtils.getProperty(k));
		}
		properties.put("properties", props.entrySet());
		properties.build(SystemUtils.getClassesPath() + "freemarker.properties");
	}
	
	public void load(ServletContext ctx){
		servletContext = ContextProxyUtils.getProxy(ctx, 
				ContextLoader.CONFIG_LOCATION_PARAM, 
				"classpath*:/_JULEWA_SPRING_.xml"
		);
		springContext = new ContextLoader();
		springContext.initWebApplicationContext(servletContext);
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T getInstance(Class<T> c){
		Map m = ContextLoader.getCurrentWebApplicationContext().getBeansOfType(c);
		if(m == null || m.isEmpty())return null;
		return (T)m.values().iterator().next();
	}
	
	public void close(){
		springContext.closeWebApplicationContext(servletContext);
	}
}
